(** Configfile.mli - Parse simple config files. *)


(** A config file store *)
type t

(** Thrown where there is a parse error *)
exception Parse_error of string

(** Thrown when a section doesn't exist *)
exception Missing_section of string

(** Thrown when an option doesn't exist *)
exception Missing_option of string

(** Thrown when an option has no value *)
exception Missing_value of string


(** An option specification *)
type option_spec = {
  opt_name	: string;	(** Option name *)
  opt_default	: string list;	(** Default value(s) *)
}

(** A section specification *)
type section_spec = {
  sec_name	: string;	(** Section name *)
  sec_opt_specs : option_spec list;
}

(** You can create a config store just from the defaults *)
val from_defaults : section_spec list -> t

(** Load config store from a file. Default values are loaded for
    sections and options not present in the file.
*)
val load : in_channel -> string -> section_spec list -> t


(** Write out a config store to a file.

    - If [save_all] is true, then options that differ from defaults
    are saved.

    - If [save_unknown] is true, then unknown options are saved.
*)
val save : t -> out_channel -> save_all:bool -> save_unknown:bool -> unit


(** Get a list of all the sections *)
val sections : t -> string list


(** Get a list of all the options and values in a given section.  Note
    that some values (option, value) pairs may be repeated. *)
val options : t -> string -> (string * string) list


(** [get t section option]

    You can query some value. This returns the last binding for that
    option. This may happen if the config file or defaults have
    multiple values.

    @raise Missing_section
    @raise Missing_option
    @raise Missing_value
*)
val get : t -> string -> string -> string


(** As mentioned in the documentation for [get], an option may have
    multiple values. This returns all of them.

    @see get
    @raise Missing_section
*)
val getmult : t -> string -> string -> string list


(** Utility functions for getting values of various types *)

val get_int   : t -> string -> string -> int
val get_float : t -> string -> string -> float


(** Add an empty section. If the section already exists then nothing
    happens.
*)
val add_section : t -> string -> t

(** Remove a section. If the section doesn't exist then nothing
    happens.
*)
val del_section : t -> string -> t


(** [add t section option value]
    Add a value to some option.
    @raise Missing_section
*)
val add : t -> string -> string -> string -> t


(** Utility functions for setting values of different types *)

val add_int   : t -> string -> string -> int -> t
val add_float : t -> string -> string -> float -> t

(** [set_mult t section option values]

    Set multiple values for option. Note that this will remove all
    previous "shadow" values for the given option.

    @raise Missing_section
*)
val set_mult : t -> string -> string -> string list -> t


(** Delete option's value from option store. This will remove the last
    binding of the option. Calling this multiple times will not raise
    an error.

    To remove {b all} values, call setmult with an empty list.
*)
val del : t -> string -> string -> t
